package com.yeskery.nut.application.netty;

import com.yeskery.nut.application.NutApplication;
import com.yeskery.nut.application.NutServer;
import com.yeskery.nut.core.*;
import com.yeskery.nut.http.netty.NettyRequest;
import com.yeskery.nut.http.netty.NettyResponse;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.*;

import java.net.InetSocketAddress;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Http请求处理器
 * @author sprout
 * 2022-06-16 11:25
 */
public class HttpRequestHandler extends SimpleChannelInboundHandler<FullHttpRequest> {

    /** 日志对象 */
    private static final Logger logger = Logger.getLogger(HttpRequestHandler.class.getName());

    /** Nut应用对象 */
    private final NutApplication nutApplication;

    /** WebSocket上下文 */
    private final WebSocketServerContext webSocketServerContext;

    /** 服务上下文 */
    private final ServerContext serverContext;

    /** 请求分发器 */
    private final Dispatcher dispatcher;

    /** Session管理器 */
    private final SessionManager sessionManager;

    /** 服务请求配置对象 */
    private final ServerRequestConfiguration serverRequestConfiguration;

    /** Nut 服务器 */
    private final NutServer nutServer;

    /**
     * 构建Http请求处理器
     * @param nutApplication Nut应用对象
     * @param webSocketServerContext WebSocket上下文
     * @param serverContext 服务上下文
     * @param dispatcher 请求分发器
     * @param sessionManager 会话管理器
     * @param serverRequestConfiguration 服务请求配置对象
     * @param nutServer Nut服务器对象
     */
    public HttpRequestHandler(NutApplication nutApplication, WebSocketServerContext webSocketServerContext,
                              ServerContext serverContext, Dispatcher dispatcher, SessionManager sessionManager,
                              ServerRequestConfiguration serverRequestConfiguration, NutServer nutServer) {
        this.nutApplication = nutApplication;
        this.webSocketServerContext = webSocketServerContext;
        this.serverContext = serverContext;
        this.dispatcher = dispatcher;
        this.sessionManager = sessionManager;
        this.serverRequestConfiguration = serverRequestConfiguration;
        this.nutServer = nutServer;
    }

    @Override
    protected void channelRead0(ChannelHandlerContext context, FullHttpRequest fullHttpRequest) throws Exception {
        //100 Continue
        if (HttpUtil.is100ContinueExpected(fullHttpRequest)) {
            context.write(new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.CONTINUE));
        }

        if (!webSocketServerContext.isWebSocketRequest(context, fullHttpRequest)) {
            try {
                InetSocketAddress remoteSocketAddress = (InetSocketAddress) context.channel().remoteAddress();
                InetSocketAddress localAddressSocketAddress = (InetSocketAddress) context.channel().localAddress();
                Request request = new NettyRequest(remoteSocketAddress, localAddressSocketAddress, serverContext,
                        sessionManager, serverRequestConfiguration, fullHttpRequest);
                Response response = new NettyResponse(nutApplication, context);
                //请求执行的方法
                nutServer.process(request, response, dispatcher, sessionManager);
            } catch (Exception e) {
                logger.log(Level.WARNING, "An Error Occurred While Closing The NettyServer Socket.", e);
                throw e;
            }
        }
    }
}
